package com.esgov.chatbot.service.impl;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.esgov.chatbot.dao.TChatbotLogDao;
import com.esgov.chatbot.entity.TChatbotLog;
import com.esgov.chatbot.entity.TChatbotSession;
import com.esgov.chatbot.dao.TChatbotSessionDao;
import com.esgov.chatbot.entity.chatbot.*;
import com.esgov.chatbot.entity.chatbot.chat.*;
import com.esgov.chatbot.service.TChatbotSessionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 文本机器人会话 服务实现类
 * </p>
 *
 * @author Eric Lao
 * @since 2025-09-16
 */
@Slf4j
@Service
public class TChatbotSessionServiceImpl extends ServiceImpl<TChatbotSessionDao, TChatbotSession> implements TChatbotSessionService {

    @Resource
    private TChatbotSessionDao tChatbotSessionDao;
    @Resource
    private TChatbotLogDao tChatbotLogDao;

    @Value("${model.url}")
    private String modelUrl;
    @Value("${model.api-key}")
    private String modelApiKey;
    @Value("${model.param-template}")
    private String modelParamTemplate;

    @Override
    public CreateChatBotSessionResponse createChatBotSession(CreateChatBotSessionRequest request) {
        // 创建会话
        TChatbotSession chatbotSession = TChatbotSession.builder()
                .userId(request.getUserId())
                .userName(request.getUserName())
                .userPhone(request.getUserPhone())
                .startTime(new Date())
                .state("SA")
                .build();
        tChatbotSessionDao.insert(chatbotSession);

        return CreateChatBotSessionResponse.builder()
                .sessionId(chatbotSession.getId())
                .greetings("小亿机器人为您服务，请问有什么可以帮您?")
                .build();
    }

    @Override
    public void endChatBotSession(EndChatBotSessionRequest request) {
        TChatbotSession chatbotSession = tChatbotSessionDao.selectById(request.getSessionId());
        if (null != chatbotSession) {
            chatbotSession.setEndTime(new Date());
            chatbotSession.setState("SE");
            tChatbotSessionDao.updateById(chatbotSession);
        }
    }

    @Override
    public FeedbackResponse feedback(FeedbackRequest request) {
        TChatbotLog chatbotLog = tChatbotLogDao.selectById(request.getMessageId());
        if (chatbotLog != null) {
            chatbotLog.setFeedback(request.getFeedback());
            tChatbotLogDao.updateById(chatbotLog);
        } else {
            log.error("==> chatbotLog is null, id: {}", request.getMessageId());
        }
        return FeedbackResponse.builder().feedback(request.getFeedback()).build();
    }

    @Override
    public ChatResponse chat(ChatRequest request) {
        TChatbotSession aiChatBotSession = tChatbotSessionDao.selectById(request.getSessionId());
        Optional.ofNullable(aiChatBotSession).orElseThrow(() -> new RuntimeException("AiChatBotSession does not exist. id: " + request.getSessionId()));
        if (!StrUtil.equals(aiChatBotSession.getState(), "SA")) {
            throw new RuntimeException(MessageFormat.format("当前会话已结束，sessionId: {0}", aiChatBotSession.getId()));
        }

        TChatbotLog questionLog = saveClientLog(request);
        TChatbotLog answerLog = createAnswerLog(request);

        List<Message> messageList = new ArrayList<>();
        modelChat(request, messageList, answerLog);

        answerLog.setContent(JSONArray.toJSONString(messageList));
        tChatbotLogDao.insert(answerLog);

        return ChatResponse.builder()
                .messageId(answerLog.getId())
                .messages(messageList)
                .sessionId(request.getSessionId())
                .build();
    }

    /**
     * 保存市民的消息
     *
     * @param request          chat接口参数
     * @return 消息实体
     */
    private TChatbotLog saveClientLog(ChatRequest request) {
        // 保存市民发送的问题
        TChatbotLog questionLog = TChatbotLog.builder()
                .sessionId(request.getSessionId())
                .content(request.getQuestion())
                .sender("C")
                .createTime(new Date()).build();
        tChatbotLogDao.insert(questionLog);
        return questionLog;
    }

    /**
     * 生成答案log
     *
     * @param request          chat接口参数
     * @return 答案log
     */
    protected TChatbotLog createAnswerLog(ChatRequest request) {
        return TChatbotLog.builder()
                .sessionId(request.getSessionId())
                .sender("R")
                .createTime(new Date())
                .build();
    }

    /**
     * 大模型Chat（通用模型接口）
     *
     * @param request     问题参数
     * @param messageList 接口返回数据
     * @param answerLog   答案实体
     */
    private void modelChat(ChatRequest request, List<Message> messageList, TChatbotLog answerLog) {
        String chatResult = "";
        String content = "";
        JSONObject params = JSONObject.parseObject(modelParamTemplate);
        //params.getJSONArray("messages").getJSONObject(0).put("content", "你是一个政务领域专家，请从专业角度回答以下问题。始终使用纯文本格式进行回复，不要返回富文本或markdown格式，以更好地呈现内容。");
        params.getJSONArray("messages").getJSONObject(0).put("content", "你是一个政务领域专家，请从专业角度回答以下问题。始终使用纯文本格式进行回复，不要返回富文本或markdown格式，以更好地呈现内容。");
        params.getJSONArray("messages").getJSONObject(1).put("content", request.getQuestion());
        log.info("\n==> url: {} \n==> params: {}", modelUrl, params);
        try (HttpResponse httpResponse = HttpRequest.post(modelUrl)
                .body(params.toJSONString())
                .header("Authorization", "Bearer " + modelApiKey)
                .header("Content-Type", "application/json")
                .timeout(300000)
                .execute()) {
            if (httpResponse.isOk()) {
                chatResult = httpResponse.body();
            }
            log.info("\n==> resp status: {} \n==> chatResult: {}", httpResponse.getStatus(), chatResult);
            JSONObject resp = JSONObject.parseObject(chatResult);
            content = getContentFromModelResponse(resp);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            content = "请求大模型报错";
        }
        answerLog.setContent(content);

        messageList.add(Message.builder()
                .type("Knowledge")
                .knowledge(MessageKnowledge.builder()
                        .id(IdUtil.fastUUID())
                        .name(request.getQuestion())
                        .hitStatement(request.getQuestion())
                        .content(content)
                        .contentType("RICH_TEXT")
                        .build()).build());
    }

    private String getContentFromModelResponse(JSONObject response) {
        String content;
        try {
            content = response.getJSONObject("message").getString("content");
        } catch (Exception e) {
            content = response.getJSONArray("choices").getJSONObject(0).getJSONObject("message").getString("content");
        }
        return content;
    }
}
